<?php

namespace app\common\service\WebSocket;

use app\Normal;
use think\facade\Cache;
use Ly\Model\ManagerLog;
use app\BaseService;
use app\common\service\UserService\UserManageService;

class WebSocketService extends BaseService
{
    public $socket_connector;
    /**
     * 管理员id
     * @access protected
     * @var    int
     */
    protected $manager_id;
    
    /**
     * 管理员名称
     * @access protected
     * @var    string
     */
    protected $manager_name;
    
    /**
     * 管理员帐号
     * @var string
     */
    protected $manager_account;
    
    /**
     * 用户信息
     * @var string
     */
    protected $_master_user;

    /**
     * 客户端连接ID
     * @var int
     */
    protected $fd;
    
    /**
     * 访问HOST
     * @var string
     */
    protected $host;
    
    /**
     * 开启socket服务验证 
     * @param array $param
     */
    
    /**
     * 排除不需要登录的模块
     */
    protected $except = [
        '/shop/Manager/Login',
        '/shop/Manager/Register',
        '/shop/Manager/ForgetPassWord',
    ];
    public function runSocketService($connection,$params = [])
    {
        $this->socket_connector = $connection;
        $this->fd               = $params['fd'];
        $this->host             = $params['host'];
        $param = $params['data'];
        try {
            $res = $this->checkParameters($param);
            if( $res['code'] != Normal::SUC ) {
                return $this->sendSocketClientMsg(Normal::returnWsStatus(Normal::WS_ERROR,$res['msg']));
            }
            $parameters = $res['data'];
            $res = $this->checkLogin($parameters);
            if( $res['code'] != Normal::SUC ) {
                return $this->sendSocketClientMsg(Normal::returnWsStatus(Normal::WS_ERROR,$res['msg']));
            }
            
            $requestMethods = explode(".", $parameters['requestMethod']);
            
            if( count($requestMethods) != 2 ) {
                return $this->sendSocketClientMsg(Normal::returnWsStatus(Normal::WS_ERROR,"requestMethod必须满足a.b格式"));
            }
            
            $module = $requestMethods[0];
            $method = $requestMethods[1];
            $socketServiceClient = "app\\common\\service\\WebSocket\\SocketService\\{$module}SocketService";
            if( !class_exists($socketServiceClient) ) {
                return $this->sendSocketClientMsg(Normal::returnWsStatus(Normal::WS_ERROR,"服务类【{$socketServiceClient}】不存在"));
            }
            if( !method_exists($socketServiceClient,$method) ) {
                return $this->sendSocketClientMsg(Normal::returnWsStatus(Normal::WS_ERROR,"服务类【{$socketServiceClient}】方法【{$method}】不存在"));
            }
            
            $requestBody = [
                'fd'            => $this->fd,
                'host'          => $this->host,
                'socket'        => $this->socket_connector,
                'requestData'   => $param['requestData'],
                '_master_user'  => $this->_master_user,
            ];
            $resServiceResult = $socketServiceClient::instance()->{$method}($requestBody);
            $manager= \app\model\BbcModel\Manager::instance()->info(['id'=>$this->_master_user['manager_id']]);
            $data = [
                'manager_id'    => $this->_master_user['manager_id'],
                'manager_name'  => $manager['name'],
                'cid'           => $this->_master_user['cid'],
                'cb_id'         => $this->_master_user['cb_id'],
                'content'       => $resServiceResult['name']??'',
                'request_param' =>$param?json_encode($param,JSON_UNESCAPED_UNICODE):'',
                'ip'            => request()->ip(),
                'url'           => request()->url(),
                'cd'            => time(),
            ];
            \app\model\BbcModel\ManagerLog::instance()->add($data);
            return $this->sendSocketClientMsg($resServiceResult);
        } catch ( \Exception $e ) {
            return $this->sendSocketClientMsg(Normal::returnWsStatus(Normal::WS_ERROR,$e->getMessage()));
        }
    }
    
    /**
     * 向socket client push 消息
     * @param array $body
     */
    protected function sendSocketClientMsg( array $body )
    {
        return $this->socket_connector->push($this->fd,json_encode($body,JSON_UNESCAPED_UNICODE));
    }
    
    /**
     * 检查登录
     * @param $param
     */
    protected function checkLogin($param)
    {        
        //如果出现APP_DEBUG_USER_ID,则登录信息就是使用当前用户系统配置的USER_ID
        if( env('APP_DEBUG_USER_ID') ) {
            $user_id = env('APP_DEBUG_USER_ID');            
            $manager= \app\model\BbcModel\Manager::instance()->info(['id'=>$user_id]);
            if(empty($manager)){
                return Normal::returnCode(Normal::NO_LOGIN,"配置用户未找到相关信息");
            }
            $cid=$manager['cid'];
            $cb_id=$manager['cb_id'];
            $group_id=$manager['group_id'];
        } else {
            //如果不在排除登录的模块里面，则需要进行登录
            if(!in_array($param['requestMethod'],$this->except)) {
                $token =$param['token'];
                if( empty($token) ) {
                    return Normal::returnCode(Normal::NO_LOGIN,"该模块需要认证");
                }
                $destoken= callApi(UserManageService::class,'keyDecrypt',$token);
                if(!$destoken){
                   return Normal::returnCode(Normal::NO_LOGIN,"token无效");
                }
                $tokendata= explode('&', $destoken);
                $user_id=$tokendata[0];
                $cid=$tokendata[1];
                $cb_id=$tokendata[2];
                $group_id=$tokendata[3];
                $redis = getRedisObj();
                $user_token = $redis->get(UserManageService::master_login_cache_key.$tokendata[0]);
                if( empty($user_token)||$user_token!=$token) {
                    return Normal::returnCode(Normal::NO_LOGIN,"登录失效或未登录");
                }
                //更新token失效时间
                $tokendata[4]=time();
                $redis->set(UserManageService::master_login_cache_key.$tokendata[0],$token, UserManageService::master_login_expire_time);
            }
        }
        if( !empty($user_id) ) 
        {
            $result_query = callApi(UserManageService::class,'checkAuth',[
                'group_id'=>$group_id,
                'cid'=>$cid,
                'cb_id'=>$cb_id,
                'path'=> $param['requestMethod']
            ]);
            if( $result_query['code'] != Normal::SUC ) {
                return $result_query;
            }
            $data=[
                'manager_id'=>$user_id,
                'cid'=>$cid,
                'cb_id'=>$cb_id,
                'group_id'=>$group_id
            ];
            $this->_master_user=$data;
            $this->manager_id=$user_id;
        }
        return Normal::returnCode(Normal::SUC,"登录验证通过",);
    }
    
    /**
     * 检查 参数
     * @param $param
     */
    protected function checkParameters($param) 
    {
        if ( empty($param['token']) ) {
            return Normal::returnCode(Normal::FAIL,"token参数缺失");
        }
        
        if ( empty($param['requestMethod']) ) {
            return Normal::returnCode(Normal::FAIL,"requestMethod参数缺失");
        }
        
        if ( !isset($param['requestData']) ) {
            return Normal::returnCode(Normal::FAIL,"requestData参数缺失");
        }
        
        return Normal::returnCode(Normal::SUC,"校验完成",$param);
    }
}